package com.mq.rabbitmq.point;

/**
* Created by Administrator on 2017/8/11.
*/

import com.mq.rabbitmq.aspect.RabbitMqContext;
import com.example.myproject.seriable.SeriableDemo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.Subject;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

import java.util.Collection;
import java.util.concurrent.Executor;

/**
 * 测试方案：先发两个消息功能
 *
 */
@ConditionalOnMissingBean(value={ConnectionFactory.class})
public class PointListener {
    @Autowired
    private Executor executor;

    //@Autowired
    private SessionDAO sessionDAO;


    /**
     *测试发现
     * @param str
     */
    //@RabbitListener(queues =AmqpConfig.ROUTINGKEY,containerFactory ="demoContainerFactory2" )
     //监听器监听指定的Queue
    //@RabbitListener(queues ="sync.test.from.apollo")    //测试动态queue,启动的时候，没有，但是test代码发送，这边还能接受
    public void processC(String str) {
        System.out.println("start processC <<<<<<<<<<<<<<PointListenerPointListenerPointListener" + str);
        //testShiroLoginoutThreadData();
        System.out.println("end processC" + str);
    }

   @RabbitListener(queues =AmqpConfig.ROUTINGKEY )
    @RabbitMqContext
   //如果之前是使用的老的对象，没有序列化Id就会报错;
   //都不会进入注解方法RabbitMqContext ，进入这里就报错了。
    public void processSeriableObject(SeriableDemo demo) {
        System.out.println("demo age:"+demo.getUserName());
    }

    //@RabbitListener(queues =AmqpConfig.ROUTINGKEY,containerFactory ="demoContainerFactory" )
    //监听器监听指定的Queue
    //@RabbitListener(queues ="sync.test.from.apollo")    //测试动态queue,启动的时候，没有，但是test代码发送，这边还能接受
    public void processObject(SeriableDemo seriableDemo) {
        System.out.println("start processC <<<<<<<<<<<<<<processObject" + seriableDemo.getAge());
        //testShiroLoginoutThreadData();
    }


    private int a =0;

    /**
     * 测试第2个人错误的登录，后面拿的登录信息是不是第一个人的登录信息？
     * 会有的
     *
     */
    private void testSecondErrorLogin(){
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken("admin","123456");
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession(false);
        System.out.println("threadName;"+Thread.currentThread().getName()+"," +"session:"+session +",id=="+(session!=null?session.getId():"")+",subject:"+SecurityUtils.getSubject()+",user:"+SecurityUtils.getSubject().getPrincipal());
        try {
            if(a ==1){
                UsernamePasswordToken erorUserName=new UsernamePasswordToken("error","123456");
                subject.login(erorUserName);   //完成登录
            }else{
                subject.login(usernamePasswordToken);   //正常登录
            }
            a++;
        }catch (Exception e){
            e.printStackTrace();
        }
        //登录信息，如果登录失败 ，拿的还是第一个错误的信息吧
        //回答是的：线程池的sessionId 一直会公用一个sessionId
        System.out.println("login finish,session:" + subject.getSession(false)+",id==="+subject.getSession(false).getId()+",subject:"+SecurityUtils.getSubject()+",thread login:"+SecurityUtils.getSubject().getPrincipal());
    }


    /**
     * 测试shiro登录了之后，线程池还会有这个数据吗
     *loginout finish,session:null,id===,subject:org.apache.shiro.subject.support.DelegatingSubject@2a51e121,user:null
     * 测试登出之后，线程绑定的Subject对象虽然指针没变，但是里面的内容都为空了；
     */
    private void testShiroLoginoutThreadData(){
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken("admin","123456");
        Subject subject = SecurityUtils.getSubject();
        System.out.println("0000000");
        subject.logout();
        System.out.println("111111111111");
        Session session = subject.getSession(false);
        System.out.println("login first threadName;"+Thread.currentThread().getName()+"," +"session:"+session +",id=="+(session!=null?session.getId():"")+",subject:"+SecurityUtils.getSubject()+",user:"+SecurityUtils.getSubject().getPrincipal());
        subject.login(usernamePasswordToken);   //正常登录
        System.out.println("login second,session:" + subject.getSession(false)+",id==="+subject.getSession(false).getId()+",subject:"+SecurityUtils.getSubject()+",thread login:"+SecurityUtils.getSubject().getPrincipal());
        subject.logout();
        Session session2 = subject.getSession(false);
        System.out.println("loginout finish,session:" +session2+ ",id==="+(session2!=null?session2.getId():"")+",subject:"+SecurityUtils.getSubject()+",user:"+ SecurityUtils.getSubject().getPrincipal());
    }

    private void testListenerLogin(){
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken("admin","123456");
        Subject subject = SecurityUtils.getSubject();
        //避免线程池在其他地方记住了一个Subject拿来这边来用，删除一边，用玩就清理。
        //不然默认线程池会记住登录的session和subject.
//        if(subject.isAuthenticated()){
//            System.out.println("用玩就清理");
//            subject.logout();
//        }
//        if(subject.isAuthenticated()){
//            System.out.println("前一次登录成功绑定了Subject,需要清理，不然还是之前绑定的simpleSession对象，没便，有id,和指是都系i阿苟纳");
//        }
        Session session = subject.getSession(false);
        System.out.println("threadName;"+Thread.currentThread().getName()+"," +"session:"+session +",id=="+(session!=null?session.getId():"")+",subject:"+SecurityUtils.getSubject()+",user:"+SecurityUtils.getSubject().getPrincipal());
        try {
            if(a ==1){
                UsernamePasswordToken erorUserName=new UsernamePasswordToken("error","123456");
                subject.login(erorUserName);   //完成登录
            }else{
                subject.login(usernamePasswordToken);   //正常登录
            }
            a++;
        }catch (Exception e){
            e.printStackTrace();
        }
        //登录信息，如果登录失败 ，拿的还是第一个错误的信息吧
        System.out.println("login finish,session:" + subject.getSession(false)+",id==="+subject.getSession(false).getId()+",subject:"+SecurityUtils.getSubject()+",thread login:"+SecurityUtils.getSubject().getPrincipal());
      //  lookQueryData();
        //避免线程池会服用这个功能
//        if(subject.isAuthenticated()){
//            System.out.println("用玩就清理");
//            subject.logout();
//        }
    }

    private void lookQueryData(){
        Collection<Session> sessions = sessionDAO.getActiveSessions();
        for(Session session:sessions){
            System.out.println("登录ip:"+session.getId());
            System.out.println("最后操作日期:"+session.getLastAccessTime());
        }
    }

    //测试shiro线程池功能
    private void testShiroThreadPool(){
        Subject subject = SecurityUtils.getSubject();
        System.out.println("Executor data:"+subject);
        System.out.println("Executor data session:"+subject.getSession(false));
        executor.execute(new Runnable() {
            @Override
            public void run() {
                Object object = subject.getPrincipal();
                System.out.println("default user:"+object);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });

    }

//    public PointListener(org.apache.shiro.mgt.SecurityManager securityManager){
//        SecurityUtils.setSecurityManager(securityManager);
//    }


    @Bean("demoContainerFactory")
    public SimpleRabbitListenerContainerFactory myContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer,
            @Qualifier("firstConnectionFactory") ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setPrefetchCount(1);
        factory.setConcurrentConsumers(1);
        configurer.configure(factory, connectionFactory);
        return factory;
    }

}

